#include "board.h"
#include <string.h>

///////////////////////////////////////////////////////////////////////////////
// gpio

#ifdef HAL_GPIO_MODULE_ENABLED

static GPIO_TypeDef* gpio_port[] = {GPIOA, GPIOB, GPIOC, GPIOD};

void gpio_direction_input(uint32_t gpio)
{
    // TODO: 设置GPIO引脚为输入模式

    // 先获取GPIO Port
    uint32_t port = gpio / 16;
    uint32_t pin  = gpio % 16;

    GPIO_InitTypeDef gpio_init_struct = {0};
    gpio_init_struct.Pin              = pin;
    gpio_init_struct.Mode             = GPIO_MODE_INPUT;
    gpio_init_struct.Pull             = GPIO_NOPULL;
    gpio_init_struct.Speed            = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(gpio_port[port], &gpio_init_struct);
}

void gpio_direction_output(uint32_t gpio)
{
    // TODO: 设置GPIO引脚为输出模式
    // 先获取GPIO Port
    uint32_t port = gpio / 16;
    uint32_t pin  = gpio % 16;

    GPIO_InitTypeDef gpio_init_struct = {0};
    gpio_init_struct.Pin              = pin;
    gpio_init_struct.Mode             = GPIO_MODE_OUTPUT_PP;
    gpio_init_struct.Pull             = GPIO_NOPULL;
    gpio_init_struct.Speed            = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(gpio_port[port], &gpio_init_struct);
}

void gpio_set_value(uint32_t gpio, uint32_t value)
{
    // TODO: 设置GPIO引脚的电平

    // 先获取GPIO Port
    uint32_t port_idx = gpio / 32;
    uint32_t pin_idx  = gpio % 32;

    // 计算出所需的pin
    uint32_t pin = (1 << pin_idx);

    HAL_GPIO_WritePin(gpio_port[port_idx], pin, (GPIO_PinState)value);
}


uint32_t gpio_get_value(uint32_t gpio)
{
    // TODO: 获取GPIO引脚的电平

    // 先获取GPIO Port
    uint32_t port_idx = gpio / 32;
    uint32_t pin_idx  = gpio % 32;

    // 计算出所需的pin
    uint32_t pin = (1 << pin_idx);

    return (uint32_t)HAL_GPIO_ReadPin(gpio_port[port_idx], pin);
}

#endif // HAL_GPIO_MODULE_ENABLED

///////////////////////////////////////////////////////////////////////////////
// uart

static USART_TypeDef* g_uart_port[] = {USART1, USART2, USART3};

void uart_send_byte(uint32_t uart, uint8_t data)
{
    while ((g_uart_port[uart]->SR & 0x40) == 0);   // 等待发送完成
    g_uart_port[uart]->DR = data;                  // 数据存入数据寄存器
}

uint8_t uart_read_byte(uint32_t uart)
{
    uint8_t data = g_uart_port[uart]->DR;
    return data;
}

void uart_send(uint32_t uart, void* data, uint32_t len)
{
    uint8_t* p = (uint8_t*)data;
    while (len--) {
        uart_send_byte(uart, *p);
        p++;
    }
}

uint8_t uart_read(uint32_t uart, void* buf, uint32_t len)
{
    uint8_t* p = (uint8_t*)buf;
    while (len--) {
        *p = uart_read_byte(uart);
        p++;
    }
    return 0;
}

void uart_bind(uint32_t uart,void* huart)
{
    
}

/////////////////////////////////////////////////////////////////////////////////
// i2c

#ifdef HAL_I2C_MODULE_ENABLED

static void* g_i2c_hanldes[3] = {NULL};
// 把i2c绑定到hal库的i2c句柄
void i2c_bind(uint32_t i2c, void* hi2c)
{
    g_i2c_hanldes[i2c] = hi2c;
}

void i2c_read(uint32_t i2c, uint16_t dev_addr, uint16_t mem_addr, uint16_t men_addr_len, void* buf,
              uint32_t len)
{
    HAL_I2C_Mem_Read(
        g_i2c_hanldes[i2c], dev_addr, mem_addr, men_addr_len, (uint8_t*)buf, len, 1000);
}
void i2c_write(uint32_t i2c, uint16_t dev_addr, uint16_t mem_addr, uint16_t men_addr_len,
               void* data, uint32_t len)
{
    HAL_I2C_Mem_Write(
        g_i2c_hanldes[i2c], dev_addr, mem_addr, men_addr_len, (uint8_t*)data, len, 1000);
}

#endif // !HAL_I2C_MODULE_ENABLED

///////////////////////////////////////////////////////////////////////////////
// spi

#ifdef HAL_SPI_MODULE_ENABLED

static void* g_spi_handles[] = {NULL};
// 把spi绑定到hal库的spi句柄
void spi_bind(uint32_t spi, void* hspi)
{
    g_spi_handles[spi] = hspi;
}
void spi_read(uint32_t spi, uint8_t* buf, uint32_t len)
{
    HAL_SPI_Receive(g_spi_handles[spi], buf, len, 1000);
}

void spi_write(uint32_t spi, uint8_t* data, uint32_t len)
{
    HAL_SPI_Transmit(g_spi_handles[spi], data, len, 1000);
}

#endif // !HAL_SPI_MODULE_ENABLED

///////////////////////////////////////////////////////////////////////////////
// delay

void delay_ms_block(uint32_t ms)
{
    HAL_Delay(ms);
}

/////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////////////
// flash

static enum { FLASH_IDLE, FLASH_READING, FLASH_WRITING } g_flash_state = FLASH_IDLE;

int32_t flash_read(void* address, void* buffer, uint32_t length)
{
    if (g_flash_state != FLASH_IDLE) {
        return -1;
    }

    g_flash_state = FLASH_READING;
    memcpy(buffer, address, length);
    g_flash_state = FLASH_IDLE;
    return 0;
}

int32_t flash_write(void* address, void* buffer, uint32_t length)
{
    if (g_flash_state != FLASH_IDLE) {
        return -1;
    }

    g_flash_state = FLASH_WRITING;

    // 解除写保护
    HAL_FLASH_Unlock();

    // 擦除扇区
    // 计算合适的擦除地址
    uint32_t addr = (uint32_t)address;
    // 计算合适的页
    uint32_t               page         = addr / FLASH_PAGE_SIZE;
    FLASH_EraseInitTypeDef erase_struct = {
        .TypeErase = FLASH_TYPEERASE_PAGES, .PageAddress = addr, .NbPages = page};
    // 擦除扇区
    uint32_t err = 0;
    if (HAL_FLASHEx_Erase(&erase_struct, &err) != HAL_OK) {
        return -1;
    }

    // 写入数据
    for (uint32_t i = 0; i < length; i += 2) {
        uint16_t data = *((uint16_t*)buffer + i / 2);
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr + i, data) != HAL_OK) {
            return -1;
        }
    }
    // 如果是奇数个字节，写入最后一个字节
    if (length % 2 == 1) {
        uint8_t data = *((uint8_t*)buffer + length - 1);
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr + length - 1, data) != HAL_OK) {
            return -1;
        }
    }

    // 重新锁定
    HAL_FLASH_Lock();

    g_flash_state = FLASH_IDLE;
    return 0;
}

/////////////////////////////////////////////////////////////////////////////////
// adc

uint16_t adc_read(uint8_t adc, uint8_t channel)
{
    // HAL_ADC_Start(&hadc1);
    return 0;
}

/////////////////////////////////////////////////////////////////////////////////
